﻿using System.Collections.Generic;
using Microsoft.Xna.Framework;
using System.Collections;
using System;

namespace ShevaEngine.Core.Modules.Graphics
{
    /// <summary>
    /// Rendering pipeline.
    /// </summary>
    public class RenderingPipeline
    {
        /// <summary>Actual count.</summary>
        public Int32 ActualCount;
        /// <summary>Allocated count.</summary>
        public Int32 AllocatedCount;
        /// <summary>Draw calls.</summary>
        public List<RenderingPackage> DrawCalls;
        /// <summary>DrawCall comparer.</summary>
        private RenderingPairComparer RenderingPairComparer;

        /// <summary>
        /// Constructor.
        /// </summary>
        public RenderingPipeline()
        {
            this.DrawCalls = new List<RenderingPackage>();
            this.AllocatedCount = this.DrawCalls.Count;
            this.ActualCount = 0;
            this.RenderingPairComparer = new RenderingPairComparer();
        }

        /// <summary>
        /// Method adds graphics object in renderer pipeline.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="drawCall"></param>
        /// <param name="world"></param>
        public void AddOpaqueGraphicsObject(DrawCallKey drawCallKey, DrawCall drawCall, Matrix worldMatrix)
        {
            if (this.ActualCount >= this.AllocatedCount)
            {
                this.DrawCalls.Add(new RenderingPackage());
                this.AllocatedCount = this.DrawCalls.Count;
            }

            RenderingPackage rPair = this.DrawCalls[this.ActualCount++];
            rPair.DrawCallKey = drawCallKey;
            rPair.DrawCall = drawCall;
            rPair.Matrix = worldMatrix;
        }

        /// <summary>
        /// Method adds graphics object in renderer pipeline.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="drawCall"></param>
        /// <param name="world"></param>
        public void AddOpaqueGraphicsObjects(DrawCallKey drawCallKey, DrawCall drawCall, Matrix[] worldMatrices)
        {
            for (int i = worldMatrices.Length - 1; i >= 0; i--)
            {
                if (this.ActualCount >= this.AllocatedCount)
                {
                    this.DrawCalls.Add(new RenderingPackage());
                    this.AllocatedCount = this.DrawCalls.Count;
                }

                RenderingPackage rPair = this.DrawCalls[this.ActualCount++];
                rPair.DrawCallKey = drawCallKey;
                rPair.DrawCall = drawCall;
                rPair.Matrix = worldMatrices[i];
            }
        }

        /// <summary>
        /// Method clears rendering pipeline.
        /// </summary>
        public void Clear()
        {
            this.ActualCount = 0;            
        }

        /// <summary>
        /// Sort.
        /// </summary>
        public void Sort()
        {
            this.DrawCalls.Sort(0, this.ActualCount, this.RenderingPairComparer);
        }
    }
}
